package demo.hdz.mediacodecdecode.customview;

import android.content.Context;
import android.graphics.Bitmap;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.View;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import demo.hdz.mediacodecdecode.Logger;
import demo.hdz.mediacodecdecode.filter.ImageNormalFilter;

/**
 * @author hdz
 * @date 2022/06/23 20:34
 */
public class ImageGLSurfaceView extends GLSurfaceView implements GLSurfaceView.Renderer {
    private static final String TAG = "ImageGLSurfaceView";
    private Bitmap bitmap;
    private int textureId = -1;
    private ImageNormalFilter filter;
    private int viewWidth;
    private int viewHeight;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what == 0) {
                adjustSize(ImageGLSurfaceView.this, viewWidth, viewHeight, msg.arg1, msg.arg2);
            }
        }
    };

    public ImageGLSurfaceView(Context context) {
        super(context);
        init();
    }

    public ImageGLSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public static int loadTexture(final Bitmap img, final int usedTexId, final boolean recycle) {
        int[] textures = new int[]{-1};
        if (usedTexId == -1) {
            GLES20.glGenTextures(1, textures, 0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
            //纹理也有坐标系，称UV坐标，或者ST坐标
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT); // S轴的拉伸方式为重复，决定采样值的坐标超出图片范围时的采样方式
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT); // T轴的拉伸方式为重复

            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img, 0);
        } else {
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, usedTexId);
            GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, img);
            textures[0] = usedTexId;
        }
        if (recycle) {
            img.recycle();
        }
        return textures[0];
    }

    private void init() {
        setEGLContextClientVersion(2);

        filter = new ImageNormalFilter(getContext(), "shader/img_normal.vert", "shader/img_normal.frag");
        setRenderer(this);

        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.d(TAG, "surfaceCreated: ");
        super.surfaceCreated(holder);

        viewWidth = getWidth();
        viewHeight = getHeight();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        super.surfaceChanged(holder, format, w, h);
        Log.d(TAG, "surfaceChanged: " + w + "," + h);
        adjustSize(this, w, h, bitmap.getWidth(), bitmap.getHeight());
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        super.surfaceDestroyed(holder);
    }

    public void setParameter(String key, int value) {
        if (filter != null) {
            filter.setParameter(key, value);
        }
        requestRender();
    }

    public void setBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        Log.d(TAG, "onSurfaceCreated: ");
        GLES20.glClearColor(0, 0, 0, 1);

        filter.init();

        // 把图片数据加载进GPU，生成对应的纹理id
        textureId = loadTexture(bitmap, textureId, true); // 加载纹理

        requestRender();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        Log.d(TAG, "onSurfaceChanged: GLES");
        // 设置窗口大小
        GLES20.glViewport(0, 0, width, height);

        Message msg = Message.obtain();
        msg.what = 0;
        msg.arg1 = width;
        msg.arg2 = height;
        handler.sendMessage(msg);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        Log.d(TAG, "onDrawFrame: ");
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

        // 根据纹理id，顶点和纹理坐标数据绘制图片
        filter.drawFrame(textureId, null);
    }


    public void adjustSize(View view, int screenWidth, int screenHeight, int videoWidth, int videoHeight) {
        Logger.d(TAG + ",adjustSize: " + screenWidth + ", " + screenHeight + ", " + videoWidth + ", " + videoHeight);
        int width = screenWidth;
        int height = screenHeight;

        //如果当前屏幕是宽屏
        if (screenWidth > screenHeight) {
            //如果当前视频为竖屏
            if (videoHeight > videoWidth) {
                width = videoWidth * height / videoHeight;
                float x = (float) (screenWidth - width) / 2.0f;
                view.setX(x);
            } else {
                width = videoWidth * height / videoHeight;
                float x = (float) (screenWidth - width) / 2.0f;
                view.setX(x);
            }
        } else {
            //如果当前视频为宽屏
            if (videoHeight < videoWidth) {
                height = videoHeight * width / videoWidth;
                float y = (float) (screenHeight - height) / 2.0f;
                view.setY(y);
            }
        }

        Logger.d(TAG + ",adjustSize: width: " + width + ", height: " + height);

        //设置SurfaceView大小为全屏幕，原来设置的尺寸是视频实际的尺寸_w*_h
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width, height);
        view.setLayoutParams(params);
    }
}
